import React, { useEffect, useState } from 'react';
import {
  Avatar,
  Button,
  Checkbox,
  Col,
  Divider,
  Input,
  message,
  Modal,
  Popconfirm,
  Row,
  Space,
  Upload,
} from 'antd';
const { Dragger } = Upload;
import RcResizeObserver from 'rc-resize-observer';
import { CheckCard, Statistic, StatisticCard } from '@ant-design/pro-components';
import WrapContent from '@/components/WrapContent';
import {
  deleteByFilePathsUsingDELETE,
  getLoginUserFileInfoUsingGET,
  renameByFilePathUsingGET,
} from '@/services/ctb-service/file';
import type { CheckboxChangeEvent } from 'antd/es/checkbox';
import type { CheckboxValueType } from 'antd/es/checkbox/Group';
import type { RcFile, UploadFile, UploadProps } from 'antd/es/upload/interface';
import { commonFileDownloadUsingGET } from '@/services/file';
import { useRequest } from 'ahooks';
import { copyTextToClipboard } from '@/utils/utils';
import { InboxOutlined, QuestionCircleOutlined, RedoOutlined } from '@ant-design/icons';
import styles from './index.less';
import { getAllowedFileType } from '@/utils/downloadfile';
import { commonUploadFilesUsingPOST } from '@/services/ctb-service/common';

const imgStyle = {
  display: 'block',
  width: 42,
  height: 42,
};

// 图片类型文件
const picturlPrefix = [
  'jpg',
  'png',
  'gif',
  'jpeg',
  'bmp',
  'webp',
  'svg',
  'psd',
  'tiff',
  'ico',
  'raw',
];

const defaultCheckedList: CheckboxValueType[] | (() => CheckboxValueType[]) = [];

const FileManage: React.FC = () => {
  const [checkedList, setCheckedList] = useState<CheckboxValueType[]>(defaultCheckedList);
  const [indeterminate, setIndeterminate] = useState(true);
  const [checkAll, setCheckAll] = useState(false);
  const [responsive, setResponsive] = useState(false);
  const [fileInfo, setFileInfo] = useState<any>({});
  const [dataSource, setDataSouce] = useState([
    {
      title: '图像分类',
      avatar: (
        <Avatar
          size={32}
          shape="square"
          src="https://gw.alipayobjects.com/zos/bmw-prod/ae0adacf-9456-4ed3-b1ab-51e4417d8d0c.svg"
        />
      ),
      description: '这是一段关于该算法的说明',
      value: 'A',
    },
    {
      title: '物体检测',
      avatar: (
        <Avatar
          size={32}
          shape="square"
          src="https://gw.alipayobjects.com/zos/bmw-prod/ae0adacf-9456-4ed3-b1ab-51e4417d8d0c.svg"
        />
      ),
      description: '这是一段关于该算法的说明',
      value: 'B',
    },
    {
      title: 'OCR自定义',
      avatar: (
        <Avatar
          size={32}
          shape="square"
          src="https://gw.alipayobjects.com/zos/bmw-prod/ae0adacf-9456-4ed3-b1ab-51e4417d8d0c.svg"
        />
      ),
      description: '这是一段关于该算法的说明',
      value: 'C',
    },
    {
      title: 'OCR',
      avatar: (
        <Avatar
          size={32}
          shape="square"
          src="https://gw.alipayobjects.com/zos/bmw-prod/ae0adacf-9456-4ed3-b1ab-51e4417d8d0c.svg"
        />
      ),
      description: '这是一段关于该算法的说明',
      value: 'D',
    },
    {
      title: '视频分类',
      avatar: (
        <Avatar
          size={32}
          shape="square"
          src="https://gw.alipayobjects.com/zos/bmw-prod/ae0adacf-9456-4ed3-b1ab-51e4417d8d0c.svg"
        />
      ),
      description: '这是一段关于该算法的说明',
      value: 'E',
    },
    {
      title: '关键点检测',
      avatar: (
        <Avatar
          size={32}
          shape="square"
          src="https://gw.alipayobjects.com/zos/bmw-prod/ae0adacf-9456-4ed3-b1ab-51e4417d8d0c.svg"
        />
      ),
      description: '这是一段关于该算法的说明',
      value: 'F',
    },
  ]);
  const [fileRenameParams, setFileRenameParams] = useState({ fileName: '未知', suffix: '.未知' });
  const [rename, setRename] = useState('');
  const [uploadModalVisible, setUploadModalVisible] = useState(false);
  const [uploadFileList, setUploadFileList] = useState<UploadFile[]>([]);
  const [uploading, setUploading] = useState(false);
  const [limitMsg, setLimitMsg] = useState(true);
  const props: UploadProps = {
    name: 'file',
    multiple: true,
    maxCount: 3,
    onChange: (info) => {
      if (info.file.status === 'removed') {
        setUploadFileList([...info.fileList.filter((item) => item.uid !== info.file.uid)]);
      }
      setUploadFileList([...info.fileList as UploadFile[]]);
    },
    beforeUpload: (file, fileList) => {
      // 判断类型是否合法
      const allowed = getAllowedFileType(file.type);
      if (!allowed) {
        message.error(`${file.name} 不是一个被允许上传的文件类型`);
        return Upload.LIST_IGNORE;
      }
      if (fileList.length > 3 && limitMsg) {
        setLimitMsg(false);
        message.error('最多只能上传3个文件');
        setTimeout(() => {
          setLimitMsg(true);
        }, 2000);
      }
      return false;
    },
    fileList: uploadFileList,
  };

  const recalculate = async () => {
    const cnt = document.getElementById('count');
    const water = document.getElementById('water');
    const icon = document.getElementById('icon');
    // 显示数字，隐藏图标
    // @ts-ignore
    icon.style.display = 'none';
    // @ts-ignore
    cnt.style.display = 'block';
    // @ts-ignore
    cnt.innerText = (fileInfo.fileUseRate * 100).toFixed(2) + '%';
    // @ts-ignore
    water.style.transform =
      // @ts-ignore
      'translate(0' + ',' + (80 - (fileInfo.fileUseRate * 100).toFixed(2)) + '%)';
  };

  // 根据checklist中选择的filePath寻找FileInfo中的文件信息
  const findFileInfoByFilePath = async () => {
    if (!fileInfo || !fileInfo.sysUserFileList) {
      return;
    }
    const file = fileInfo.sysUserFileList.filter((item: any) => item.filePath === checkedList[0]);
    const originalName = file[0].originalName;
    // 取出后缀
    const suffix = originalName.substring(originalName.lastIndexOf('.') + 1);
    const fileName = originalName.substring(0, originalName.lastIndexOf('.'));
    setFileRenameParams({ fileName: fileName, suffix: '.' + suffix });
    setRename(fileName);
  };

  const changeRenameValue = (e: any) => {
    if (e && e.target && e.target.value) {
      setRename(e.target.value);
    }
  };

  const onChange = (list: any) => {
    setCheckedList(list);
    setIndeterminate(!!list.length && list.length < dataSource.length);
    setCheckAll(list.length === dataSource.length);
  };

  const onCheckAllChange = (e: CheckboxChangeEvent) => {
    setCheckedList(e.target.checked ? dataSource.map((item) => item.value) : []);
    setIndeterminate(false);
    setCheckAll(e.target.checked);
  };

  const constructDatasource = (result: any) => {
    const data = [] as any;
    // 遍历并组装成 DataSource 对象
    result.forEach((item: any) => {
      // 取出图片后缀，最后一个小数点
      const suffix = item.filePath.substring(item.filePath.lastIndexOf('.') + 1);
      const fileSrc = picturlPrefix.includes(suffix)
        ? item.filePath
        : 'https://gw.alipayobjects.com/zos/bmw-prod/ae0adacf-9456-4ed3-b1ab-51e4417d8d0c.svg';
      data.push({
        title: item.originalName,
        avatar: <Avatar size={48} shape="square" src={fileSrc} style={{ borderRadius: '12px' }} />,
        description: '上传时间:' + item.createTime,
        value: item.filePath,
        // 随机设置大小
        size: 'default',
      });
    });
    setDataSouce(data);
  };

  const getUserFileInfo = async () => {
    const resp = await getLoginUserFileInfoUsingGET();
    if (resp.code === 200) {
      await setFileInfo(resp.result);
      await constructDatasource(resp.result.sysUserFileList);
    }
  };

  const { run } = useRequest(() => getUserFileInfo(), {
    refreshDeps: [],
  });

  const { run: recal } = useRequest(() => recalculate(), {
    manual: true,
    pollingWhenHidden: false,
    pollingInterval: 3000,
  });

  const downloadFileWithDelete = async (isDelete: boolean) => {
    const fileName = fileInfo.sysUserFileList
      .map((item: any) => item.filePath)
      .filter((item: any) => {
        return checkedList.includes(item);
      });
    await commonFileDownloadUsingGET({ fileName: fileName, delete: isDelete });
    message.success('下载成功');
    // 重新获取数据
    await run();
    await run();
  };

  const renameFile = async () => {
    const result = await renameByFilePathUsingGET({
      filePath: checkedList[0],
      newFileName: rename + fileRenameParams.suffix,
    } as any);
    if (result.code === 200) {
      message.success('重命名成功');
      // 重新获取数据
      await run();
      await run();
    } else {
      message.error('重命名失败');
    }
  };

  const deleteFiles = async () => {
    const res = await deleteByFilePathsUsingDELETE({ filePaths: checkedList } as any);
    setCheckedList([]);
    setIndeterminate(false);
    setCheckAll(false);
    if (res.code === 200) {
      message.success('删除成功');
      // 重新获取数据
      await run();
      await run();
    } else {
      message.error('删除失败');
    }
  };

  const handleUpload = async () => {
    setUploading(true);
    const formData = new FormData();
    // 将filelist中的每一个originalFileObj转换为file数组并设置给uploadFileList antd的已知缺陷
    const fileList = uploadFileList.map((file) => {
      return file.originFileObj;
    });
    fileList.forEach((file) => {
      formData.append('files', file as RcFile);
    });
    // @ts-ignore
    await commonUploadFilesUsingPOST(formData, { headers: {} })
      .then((res) => {
        if (res.code === 200) {
          message.success(res.msg);
        } else {
          message.warn(res.msg);
        }
      })
      .catch((err) => {
        message.error(err.msg);
      })
      .finally(() => {
        setUploadFileList([]);
        setUploadModalVisible(false);
        setUploading(false);
      });
    await run();
    await run();
  };

  // 选择元素只有一个时触发各种逻辑，所以需要重新计算
  useEffect(() => {
    if (checkedList.length === 1) {
      findFileInfoByFilePath();
    }
  }, [checkedList]);

  // 动效初始化
  useEffect(() => {
    const cnt = document.getElementById('count');
    const water = document.getElementById('water');
    const icon = document.getElementById('icon');
    let percent = cnt?.innerText;
    const interval = setInterval(function () {
      // @ts-ignore
      percent++;
      // @ts-ignore
      cnt.innerHTML = percent;
      // @ts-ignore
      water.style.transform = 'translate(0' + ',' + (100 - percent) + '%)';
      // @ts-ignore
      if (percent >= 105) {
        // @ts-ignore
        icon.style.display = 'block';
        clearInterval(interval);
      }
    }, 60);
  }, []);

  return (
    <WrapContent>
      <Divider>统计数据</Divider>
      <Row gutter={[16, 16]} justify="center" align="middle">
        <Col span={3} />
        <Col span={18}>
          <Row gutter={[16, 16]} justify="center" align="middle">
            <RcResizeObserver
              key="resize-observer"
              onResize={(offset) => {
                setResponsive(offset.width < 539);
              }}
            >
              <StatisticCard.Group direction={responsive ? 'column' : 'row'}>
                <StatisticCard
                  statistic={{
                    title: '内存总量',
                    suffix: 'MB',
                    value: fileInfo.fileAllotSizeMB,
                    icon: (
                      <>
                        <svg
                          version="1.1"
                          xmlns="http://www.w3.org/2000/svg"
                          x="0px"
                          y="0px"
                          style={{ display: 'none' }}
                        >
                          <symbol id="wave">
                            <path d="M420,20c21.5-0.4,38.8-2.5,51.1-4.5c13.4-2.2,26.5-5.2,27.3-5.4C514,6.5,518,4.7,528.5,2.7c7.1-1.3,17.9-2.8,31.5-2.7c0,0,0,0,0,0v20H420z" />
                            <path d="M420,20c-21.5-0.4-38.8-2.5-51.1-4.5c-13.4-2.2-26.5-5.2-27.3-5.4C326,6.5,322,4.7,311.5,2.7C304.3,1.4,293.6-0.1,280,0c0,0,0,0,0,0v20H420z" />
                            <path d="M140,20c21.5-0.4,38.8-2.5,51.1-4.5c13.4-2.2,26.5-5.2,27.3-5.4C234,6.5,238,4.7,248.5,2.7c7.1-1.3,17.9-2.8,31.5-2.7c0,0,0,0,0,0v20H140z" />
                            <path d="M140,20c-21.5-0.4-38.8-2.5-51.1-4.5c-13.4-2.2-26.5-5.2-27.3-5.4C46,6.5,42,4.7,31.5,2.7C24.3,1.4,13.6-0.1,0,0c0,0,0,0,0,0l0,20H140z" />
                          </symbol>
                        </svg>
                        <div className={styles.box}>
                          <div className={styles.percent}>
                            <div className={styles.percentNum} id="count">
                              0
                            </div>
                            <RedoOutlined
                              onClick={() => recal()}
                              id="icon"
                              className={styles.inIcon}
                            />
                          </div>
                          <div id="water" className={styles.water}>
                            <svg
                              viewBox="0 0 560 20"
                              className={`${styles.water_wave} ${styles.water_wave_back}`}
                            >
                              <use xlinkHref="#wave" />
                            </svg>
                            <svg
                              viewBox="0 0 560 20"
                              className={`${styles.water_wave} ${styles.water_wave_front}`}
                            >
                              <use xlinkHref="#wave" />
                            </svg>
                          </div>
                        </div>
                      </>
                    ),
                  }}
                />
                <StatisticCard
                  statistic={{
                    title: '文件总数 / 限制数',
                    suffix: '/' + fileInfo.fileLimitCount + ' 个',
                    value: fileInfo.fileCount,
                    icon: (
                      <img
                        style={imgStyle}
                        src="https://gw.alipayobjects.com/mdn/rms_7bc6d8/afts/img/A*FPlYQoTNlBEAAAAAAAAAAABkARQnAQ"
                        alt="icon"
                      />
                    ),
                  }}
                >
                  <Button style={{ marginTop: 16, borderRadius: '12px' }}>升级会员</Button>
                </StatisticCard>
                <Divider type={responsive ? 'horizontal' : 'vertical'} />
                <StatisticCard
                  statistic={{
                    title: '使用内存',
                    suffix: fileInfo.fileTotalSizeMB > 1 ? ' MB' : ' KB',
                    value:
                      fileInfo.fileTotalSizeMB > 1
                        ? fileInfo.fileTotalSizeMB?.toFixed(2)
                        : fileInfo.fileTotalSizeKB?.toFixed(2),
                    description: (
                      <Statistic
                        title="占比"
                        value={(fileInfo.fileUseRate * 100).toFixed(2)}
                        suffix="%"
                      />
                    ),
                  }}
                  chart={
                    <img
                      src="https://gw.alipayobjects.com/zos/alicdn/ShNDpDTik/huan.svg"
                      alt="百分比"
                      width="100%"
                    />
                  }
                  chartPlacement="left"
                />
                <StatisticCard
                  statistic={{
                    title: '闲置内存',
                    suffix: fileInfo.fileFreeSizeMB > 1 ? ' MB' : ' KB',
                    value:
                      fileInfo.fileFreeSizeMB > 1
                        ? fileInfo.fileFreeSizeMB?.toFixed(2)
                        : fileInfo.fileFreeSizeaKB?.toFixed(2),
                    description: (
                      <Statistic
                        title="占比"
                        value={(fileInfo.fileFreeRate * 100).toFixed(2)}
                        suffix="%"
                      />
                    ),
                  }}
                  chart={
                    <img
                      src="https://gw.alipayobjects.com/zos/alicdn/6YR18tCxJ/huanlv.svg"
                      alt="百分比"
                      width="100%"
                    />
                  }
                  chartPlacement="left"
                />
              </StatisticCard.Group>
            </RcResizeObserver>
          </Row>
          <Divider>文件一览</Divider>
          <Space.Compact block direction={responsive ? 'vertical' : 'horizontal'}>
            <Checkbox
              indeterminate={indeterminate}
              onChange={onCheckAllChange}
              checked={checkAll}
              style={{ padding: '4px 16px 0 32px' }}
            >
              全选
            </Checkbox>
            <Popconfirm
              placement="top"
              title="当前操作会删除所有勾选的文件，是否继续？"
              icon={<QuestionCircleOutlined style={{ color: 'red' }} />}
              onConfirm={() => deleteFiles()}
              okText="是"
              cancelText="否"
            >
              <Button type="primary" danger disabled={checkedList.length === 0}>
                删除
              </Button>
            </Popconfirm>
            <Popconfirm
              placement="top"
              title="当前操作会在下载到本地之后删除该文件，是否继续？"
              icon={<QuestionCircleOutlined style={{ color: 'red' }} />}
              onConfirm={() => downloadFileWithDelete(true)}
              okText="是"
              cancelText="否"
            >
              <Button
                type="primary"
                danger
                disabled={checkedList.length !== 1}
                style={{ marginRight: '1px' }}
              >
                下载后删除
              </Button>
            </Popconfirm>
            <Button
              type="primary"
              disabled={checkedList.length !== 1}
              onClick={() => downloadFileWithDelete(false)}
            >
              下载到本地
            </Button>
            <Button type="primary" onClick={() => setUploadModalVisible(true)}>
              上传
            </Button>
            <Popconfirm
              placement="top"
              title={
                <Input
                  key={checkedList[0] as any}
                  addonAfter={fileRenameParams.suffix}
                  defaultValue={fileRenameParams.fileName}
                  onChange={(event) => changeRenameValue(event)}
                />
              }
              onConfirm={renameFile}
              showCancel={false}
              okText="改名"
            >
              <Button type="primary" disabled={checkedList.length !== 1}>
                重命名
              </Button>
            </Popconfirm>
            <Button
              type="link"
              disabled={checkedList.length !== 1}
              onClick={() => copyTextToClipboard(window.location.origin + checkedList[0])}
            >
              复制链接
            </Button>
          </Space.Compact>
          <Divider />
          <Row gutter={[16, 16]} justify="space-around" align="middle">
            <CheckCard.Group
              onChange={onChange}
              multiple
              style={{ width: '100%', marginLeft: '40px' }}
              size="small"
              options={dataSource}
              value={checkedList}
            />
          </Row>
        </Col>
        <Col span={3} />
      </Row>
      <Modal
        centered
        title="文件上传"
        open={uploadModalVisible}
        onOk={handleUpload}
        onCancel={() => {
          setUploadModalVisible(false);
          setUploadFileList([]);
        }}
        okText="上传"
        cancelText="取消"
        confirmLoading={uploading}
      >
        <Dragger {...props}>
          <p className="ant-upload-drag-icon">
            <InboxOutlined />
          </p>
          <p className="ant-upload-text">点击或拖动文件上传</p>
          <p className="ant-upload-hint">
            支持批量上传，同一批最多上传三个文件。
          </p>
          <p className="ant-upload-hint">
            严禁上传非法文件，一经发现，将封禁IP。
          </p>
          <p className="ant-upload-hint">
            支持文件类型: doc、docx、xls、xlsx、ppt、pptx、
          </p>
          <p className="ant-upload-hint">
            pdf、txt、gif、jpeg、jpg、png、bmp
          </p>
        </Dragger>
      </Modal>
    </WrapContent>
  );
};

export default FileManage;
